/*
 * BufferManager.hpp
 *
 *  Created on: May 2, 2012
 *      Author: Ka Wai Lo
 */

#ifndef BUFFERMANAGER_HPP_
#define BUFFERMANAGER_HPP_

#include "BufferFrame.hpp"

#include <string>
#include <vector>
#include <list>
#include <pthread.h>
#include <iostream> // #include here cuz BufferManagerTest requires it...

class BufferManager {
public:
	BufferManager(const std::string& filename, unsigned size);
	virtual ~BufferManager();
	BufferFrame& fixPage(unsigned pageId, bool exclusive);
	void unfixPage(BufferFrame& frame, bool isDirty);

private:
	int fd; // C file descriptor for mmap()

	std::vector<BufferFrame*> vBuffer;
	std::vector<pthread_rwlock_t> vLock;
	std::vector<unsigned> viPageId; // viPageId[vecId] = pageId: pageId of file
	std::vector<unsigned> vbAccessed;  // Vector storing fixed pages (which cannot be freed)
	//std::vector<int> vbFixedOnce; // Vector storing fixed pages (which cannot be freed)
	std::vector<int> viVecId; // viVecId[pageId] = vecId: id on vector vBuffer. i.e. id of the BufferFrame

	int iVecCnt;
	unsigned iPageCnt;
	unsigned iLastPageSize;
	std::list<int> liHot;   // List storing hot pages
	std::list<int> liOnce;  // List storing pages accessed once
	std::list<int> liFree;  // List storing pages that are free
	pthread_mutex_t csFixNewPage;
	pthread_mutex_t csChangeList;
	pthread_mutex_t csFreePage;
	pthread_mutex_t csAccessLock;

	int acquireVecId(const unsigned iPageId, const bool bExclusive);
	bool assignVecToPage(const unsigned iPageId, const int iVecId);
	bool freeVec(const int iVecId, const bool bExclusive);
	bool accessLockCS(const int iVecId, const bool bLock, const bool bExclusive, const bool bBlocking);
};

#endif /* BUFFERMANAGER_HPP_ */
